﻿using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

using Ionic.Zip;

namespace Gamey.SNES
{
    // This code owes its existence to the following website:
    // http://romhack.wikia.com/wiki/SNES_header

    public class SmcHeaderReader
    {
        const int NameLength = 21;

        static readonly int[] PossibleHeaderOffsets = new int[] { 0x7fc0, 0xffc0, 0x81c0, 0x101c0 };
        static readonly Regex NameMatcher = new Regex(@"^[A-Z1-9 \-\!]+$", RegexOptions.Compiled | RegexOptions.IgnoreCase);

        public SnesRomInfo ReadZipFile(string zipFilePath)
        {
            var info = new SnesRomInfo();

            using (ZipFile zipFile = ZipFile.Read(zipFilePath))
            {
                ZipEntry smcFileEntry = zipFile.Entries.FirstOrDefault(e => Path.GetExtension(e.FileName) == ".smc");

                if (smcFileEntry != null)
                {
                    byte[] smcFileContents = ReadZipEntry(smcFileEntry);
                    PopulateSnesRomInfoFromSmcFile(smcFileContents, info);
                }
            }

            return info;
        }

        byte[] ReadZipEntry(ZipEntry zipEntry)
        {
            using (var stream = new MemoryStream())
            {
                zipEntry.Extract(stream);
                return stream.ToArray();
            }
        }

        void PopulateSnesRomInfoFromSmcFile(byte[] smcFileContents, SnesRomInfo info)
        {
            foreach (int offset in PossibleHeaderOffsets)
            {
                string name = Encoding.ASCII.GetString(smcFileContents, offset, NameLength);
                
                if (NameMatcher.IsMatch(name))
                {
                    info.Name = name.Trim();
                    break;
                }
            }
        }
    }
}
